<!DOCTYPE HTML>
<!--generated with sswg-->
<html lang="en">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
    <title> ursina engine collision</title>
    <link rel="stylesheet" href="sswg.css">
    <link rel="stylesheet" href="style.css">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<div style="max-width:1200px; margin:auto;">
<div style="text-align:left;">
<br>
<a href="index.html"><img src="ursina_logo_wireframe.webp" style="width:50px; height:auto; margin-right:10px;"/></a> <a href=" installation.html" class="button">Download</a> <a href=" documentation.html" class="button">Documentation</a> <a href=" api_reference_v8_2_0/index.html" class="button">API Reference</a> <a href=" samples.html" class="button">Samples</a> <a href=" asset_store.html" class="button">Asset Store</a> <a href=" donate.html" class="button">Donate</a><br>
<div class="sidebar"><br>
<b><a href="documentation.html">Documentation</a></b><br>
<br>
<a href="installation.html">Installation</a><br>
<br>
<a href="entity_basics.html">Entity Basics</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#What is an Entity?">What is an Entity?</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Model">Model</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Texture">Texture</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Color">Color</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Position">Position</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Rotation">Rotation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Scale">Scale</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Update">Update</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Input">Input</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Mouse Input">Mouse Input</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="entity_basics.html#Other Magic Functions">Other Magic Functions</a><br>
<br>
<a href="coordinate_system.html">Coordinate System</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="coordinate_system.html#Entity Coordinate System">Entity Coordinate System</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="coordinate_system.html#UI Coordinate System">UI Coordinate System</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="coordinate_system.html#Rotation">Rotation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="coordinate_system.html#Origin">Origin</a><br>
<br>
<a href="collision.html">Collision</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#Adding Colliders">Adding Colliders</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#raycast()">raycast()</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#boxcast()">boxcast()</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#intersects()">intersects()</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#HitInfo">HitInfo</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#Distance Check">Distance Check</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="collision.html#Mouse Collision">Mouse Collision</a><br>
<br>
<a href="text.html">Text</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="text.html#Text">Text</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="text.html#Font and Resolution">Font and Resolution</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="text.html#Changing Text of Prefabs">Changing Text of Prefabs</a><br>
<br>
<a href="animation.html">Animation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="animation.html#SpriteSheetAnimation (2D)">SpriteSheetAnimation (2D)</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="animation.html#Animation (2D)">Animation (2D)</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="animation.html#Actor (3D)">Actor (3D)</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="animation.html#FrameAnimation3D (3D)">FrameAnimation3D (3D)</a><br>
<br>
<br>
<a href="networking.html">Networking</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#~~ Networking Concepts ~~">~~ Networking Concepts ~~</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#How Data Goes from Point A to Point B">How Data Goes from Point A to Point B</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#IP Addresses">IP Addresses</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Ports">Ports</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Communication Protocols">Communication Protocols</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#References">References</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#~~ Game Networking Concepts ~~">~~ Game Networking Concepts ~~</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Multiplayer Preparations">Multiplayer Preparations</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Sending Inputs">Sending Inputs</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Sending Game State">Sending Game State</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Client Authoritative">Client Authoritative</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Server Authoritative">Server Authoritative</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Deterministic Lockstep">Deterministic Lockstep</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Snapshot Interpolation">Snapshot Interpolation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Server Side Lag Compensation">Server Side Lag Compensation</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Client Side Prediction">Client Side Prediction</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#References">References</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#~~ Introduction to Ursina Networking ~~">~~ Introduction to Ursina Networking ~~</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Limitations">Limitations</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Basics">Basics</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="networking.html#Samples">Samples</a><br>
<br>
<a href="faq.html">F.A.Q.</a><br>
<br>
<a href="building.html">Build and Release</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="building.html#Building Your App with ursina.build">Building Your App with ursina.build</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="building.html#Building with Nuitka">Building with Nuitka</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;• <a href="building.html#Building Your App with auto-py-to-exe">Building Your App with auto-py-to-exe</a><br>
<br>
<br>
</div><br>
<br>
<h1 id="Collision">
Collision
</h1><br>
<h2 id="Adding Colliders">
Adding Colliders
</h2><br>
<code_block id="code_block_0"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_0)">copy</button>e = <olive>Entity</olive>(<olive>model</olive>=<green>'sphere'</green>, x=<yellow>2</yellow>)
e.collider = <green>'box'</green>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<gray># add BoxCollider based on entity's bounds.</gray>
e.collider = <green>'sphere'</green>&nbsp;&nbsp; <gray># add SphereCollider based on entity's bounds.</gray>
e.collider = <green>'mesh'</green>&nbsp;&nbsp;&nbsp;&nbsp; <gray># add MeshCollider based on entity's bounds.</gray>

e.collider = BoxCollider(e, center=Vec3(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>0</yellow>), size=Vec3(<yellow>1</yellow>,<yellow>1</yellow>,<yellow>1</yellow>))&nbsp;&nbsp; <gray># add BoxCollider at custom positions and size.</gray>
e.collider = SphereCollider(e, center=Vec3(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>0</yellow>), radius=.<yellow>7</yellow><yellow>5</yellow>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<gray># add SphereCollider at custom positions and size.</gray>
e.collider = MeshCollider(e, mesh=e.model, center=Vec3(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>0</yellow>))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<gray># add MeshCollider with custom shape and center.</gray>
</code_block>
<br>
Usually you add the collider when you create the Entity, but make sure you set the model<br>
before setting the collider if you want it to fit its bounds.<br>
<br>
<code_block id="code_block_1"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_1)">copy</button>e = <olive>Entity</olive>(<olive>model</olive>=<green>'cube'</green>, <olive>collider</olive>=<green>'box'</green>)
</code_block>
<br>
<h2 id="raycast()">
raycast()
</h2><br>
<code_block id="code_block_2"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_2)">copy</button>raycast(origin, direction=(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>1</yellow>), distance=inf, traverse_target=scene, <olive>ignore</olive>=list(), debug=False)
</code_block>
<br>
Casts a ray from *origin*, in *direction*, with length *distance* and returns<br>
a HitInfo containing information about what it hit. This ray will only hit entities with a collider.<br>
<br>
Use optional *traverse_target* to only be able to hit a specific entity and its children/descendants.<br>
Use optional *ignore* list to ignore certain entities.<br>
Setting debug to True will draw the line on screen.<br>
<br>
Example where we only move if a wall is not hit:<br>
<br>
<code_block id="code_block_3"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_3)">copy</button><purple>from</purple> ursina <purple>import</purple> *
app = Ursina()

class Player(<olive>Entity</olive>):

&nbsp;&nbsp;&nbsp;&nbsp;<purple>def</purple> update(self):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.direction = Vec3(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.forward * (held_keys[<green>'w'</green>] - held_keys[<green>'s'</green>])
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ self.right * (held_keys[<green>'d'</green>] - held_keys[<green>'a'</green>])
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;).normalized()&nbsp;&nbsp;<gray># get the direction we're trying to walk in.</gray>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;origin = self.world_position + (self.up*.<yellow>5</yellow>) <gray># the ray should start slightly up <purple>from</purple> the ground so we can walk up slopes or walk over small objects.</gray>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hit_info = raycast(origin , self.direction, <olive>ignore</olive>=(self,), distance=.<yellow>5</yellow>, debug=False)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<purple>if</purple> <purple>not</purple> hit_info.hit:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.position += self.direction * <yellow>5</yellow> * time.dt

Player(<olive>model</olive>=<green>'cube'</green>, origin_<olive>y</olive>=-.<yellow>5</yellow>, <olive>color</olive>=color.orange)
wall_left = <olive>Entity</olive>(<olive>model</olive>=<green>'cube'</green>, <olive>collider</olive>=<green>'box'</green>, scale_<olive>y</olive>=<yellow>3</yellow>, origin_<olive>y</olive>=-.<yellow>5</yellow>, <olive>color</olive>=color.azure, x=-<yellow>4</yellow>)
wall_right = duplicate(wall_left, x=<yellow>4</yellow>)
camera.y = <yellow>2</yellow>

app.run()
</code_block>
<br>
<br>
<h2 id="boxcast()">
boxcast()
</h2><code_block id="code_block_4"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_4)">copy</button>boxcast(origin, direction=(<yellow>0</yellow>,<yellow>0</yellow>,<yellow>1</yellow>), distance=<yellow>9</yellow><yellow>9</yellow><yellow>9</yellow><yellow>9</yellow>, <olive>thickness</olive>=(<yellow>1</yellow>,<yellow>1</yellow>), traverse_target=scene, <olive>ignore</olive>=list(), debug=False)&nbsp;&nbsp; <gray># similar to raycast, but with width and height</gray>
</code_block>
<br>
boxcast is similar to raycast, but the "ray" has thickness, height and width.<br>
<br>
<br>
<h2 id="intersects()">
intersects()
</h2><br>
Check if a entity (with a collider) intersects other entities with colliders.<br>
<br>
<code_block id="code_block_5"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_5)">copy</button><purple>from</purple> ursina <purple>import</purple> *


app = Ursina()

player = <olive>Entity</olive>(<olive>model</olive>=<green>'cube'</green>, <olive>color</olive>=color.orange, <olive>collider</olive>=<green>'box'</green>, origin_<olive>y</olive>=-.<yellow>5</yellow>)
trigger_box = <olive>Entity</olive>(<olive>model</olive>=<green>'wireframe_cube'</green>, <olive>color</olive>=color.gray, <olive>scale</olive>=<yellow>2</yellow>, <olive>collider</olive>=<green>'box'</green>, <olive>position</olive>=Vec3(<yellow>1</yellow>,<yellow>0</yellow>,<yellow>2</yellow>), origin_<olive>y</olive>=-.<yellow>5</yellow>)
EditorCamera()

<purple>def</purple> update():
&nbsp;&nbsp;&nbsp;&nbsp;player.z += (held_keys[<green>'w'</green>] - held_keys[<green>'s'</green>]) * time.dt * <yellow>6</yellow>
&nbsp;&nbsp;&nbsp;&nbsp;player.x += (held_keys[<green>'d'</green>] - held_keys[<green>'a'</green>]) * time.dt * <yellow>6</yellow>

&nbsp;&nbsp;&nbsp;&nbsp;<purple>if</purple> player.intersects(trigger_box).hit:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trigger_box.color = color.lime
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<blue>print</blue>(<green>'player is inside trigger box'</green>)
&nbsp;&nbsp;&nbsp;&nbsp;<purple>else</purple>:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trigger_box.color = color.gray

app.run()
</code_block>
<br>
<br>
<br>
<br>
<h2 id="HitInfo">
HitInfo
</h2><br>
All of these functions will return a HitInfo. This contains information about what it hit.<br>
<br>
<code_block id="code_block_6"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_6)">copy</button>hit = None
entity = None
point = None
world_point = None
distance = math.inf
normal = None
world_normal = None
hits = []
entities = []
</code_block>
<br>
<h2 id="Distance Check">
Distance Check
</h2><br>
Sometimes it enough to just check the distance between two entities.<br>
For example if you want a pickup:<br>
<br>
<code_block id="code_block_7"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_7)">copy</button><purple>from</purple> ursina <purple>import</purple> *
<purple>from</purple> ursina.prefabs.first_person_controller <purple>import</purple> FirstPersonController


app = Ursina()

ground = <olive>Entity</olive>(<olive>model</olive>=<green>'plane'</green>, <olive>texture</olive>=<green>'grass'</green>, <olive>scale</olive>=<yellow>1</yellow><yellow>0</yellow>, <olive>collider</olive>=<green>'box'</green>)
player = FirstPersonController(<olive>model</olive>=<green>'cube'</green>, origin_<olive>y</olive>=-.<yellow>5</yellow>, <olive>color</olive>=color.orange, has_pickup=False)
camera.z = -<yellow>5</yellow>

pickup = <olive>Entity</olive>(<olive>model</olive>=<green>'sphere'</green>, <olive>position</olive>=(<yellow>1</yellow>,.<yellow>5</yellow>,<yellow>3</yellow>))

<purple>def</purple> update():
&nbsp;&nbsp;&nbsp;&nbsp;<purple>if</purple> <purple>not</purple> player.has_pickup and distance(player, pickup) &lt; pickup.scale_x / <yellow>2</yellow>:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<blue>print</blue>(<green>'pickup'</green>)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;player.has_pickup = True
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pickup.animate_scale(<yellow>0</yellow>, duration=.<yellow>1</yellow>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;destroy(pickup, dela<olive>y</olive>=.<yellow>1</yellow>)

app.run()
</code_block>
<br>
<br>
<h2 id="Mouse Collision">
Mouse Collision
</h2><br>
The mouse does raycast automatically.<br>
Both UI elements(Entities parented to camera.ui) and Entities in 3d space (parented to scene) can<br>
get hit as long as they have a collider. UI elements will however block things behind them.<br>
<br>
<code_block id="code_block_8"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_8)">copy</button>mouse.hovered_entity&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returns
mouse.normal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<gray># returns the normal of the polygon, in local space.</gray>
mouse.world_normal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<gray># returns the normal of the polygon, in world space.</gray>
mouse.point&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <gray># returns the point hit, in local space</gray>
mouse.world_point&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <gray># returns the point hit, in world space</gray>
</code_block>
<br>
Handling clicks is very easy, just add a collider and on_click.<br>
The on_click function will then be called when you click on the Entity with the mouse.<br>
<br>
<code_block id="code_block_9"><button class="copy_code_button" onclick="copy_to_clipboard(code_block_9)">copy</button><purple>def</purple> action():
&nbsp;&nbsp;&nbsp;&nbsp;<blue>print</blue>(<green>'Ow! That hurt!'</green>)

<olive>Entity</olive>(<olive>model</olive>=<green>'quad'</green>, <olive>parent</olive>=camera.ui, <olive>scale</olive>=.<yellow>1</yellow>, <olive>collider</olive>=<green>'box'</green>, <olive>on_click</olive>=action) <gray># on_click should be a function/callable/Func/Sequence</gray>
</code_block>
<br>
<script>
function copy_to_clipboard(containerid) {
    var range = document.createRange()
    range.selectNode(containerid)
    window.getSelection().removeAllRanges()
    window.getSelection().addRange(range)
    document.execCommand("copy")
    window.getSelection().removeAllRanges()
}
</script>
<br>
<br>
</body>
</html>